I. Preliminaries

Loading libraries

library("tidyverse")
library("tibble")
library("msigdbr")
library("ggplot2")
library("TCGAbiolinks")
library("RNAseqQC")
library("DESeq2")
library("ensembldb")
library("purrr")
library("magrittr")
library("vsn")
library("matrixStats")
library("dplyr")
library("grex")

Constants

DATA_DIR <- "data/GTEx/"

II. Loading the GTEx annotations

Download these files by running:

wget https://storage.googleapis.com/adult-gtex/annotations/v8/metadata-files/GTEx_Analysis_v8_Annotations_SampleAttributesDS.txt -P data/GTEx/
wget https://storage.googleapis.com/adult-gtex/annotations/v8/metadata-files/GTEx_Analysis_v8_Annotations_SubjectPhenotypesDS.txt -P data/GTEx/
sample.df <- read.delim(paste0(DATA_DIR, "GTEx_Analysis_v8_Annotations_SampleAttributesDS.txt"), as.is = TRUE, header = TRUE, row.names = 1)
subject.df <- read.delim(paste0(DATA_DIR, "GTEx_Analysis_v8_Annotations_SubjectPhenotypesDS.txt"), as.is = TRUE, header = TRUE, row.names = 1)

The DTHHRDY column refers to the 4-point Hardy scale: https://www.ncbi.nlm.nih.gov/projects/gap/cgi-bin/variable.cgi?study_id=phs000424.v4.p1&phv=169092

Refer to the metadata files here for more information: https://gtexportal.org/home/downloads/adult-gtex/metadata

subject.df

Refer to the metadata files here for more information: https://gtexportal.org/home/downloads/adult-gtex/metadata

sample.df

Extract entries that pertain to transcriptomic (RNA) data.

rnaseq.sample.df <- sample.df[sample.df["SMAFRZE"] == "RNASEQ", ]
rnaseq.sample.df

III. Filtering colon samples

The SMTSD column refers to the tissue type (i.e., the area from which the sample was taken).

as.matrix(sort(table(rnaseq.sample.df["SMTSD"]), decreasing = TRUE))
                                          [,1]
Muscle - Skeletal                          803
Whole Blood                                755
Skin - Sun Exposed (Lower leg)             701
Adipose - Subcutaneous                     663
Artery - Tibial                            663
Thyroid                                    653
Nerve - Tibial                             619
Skin - Not Sun Exposed (Suprapubic)        604
Lung                                       578
Esophagus - Mucosa                         555
Adipose - Visceral (Omentum)               541
Esophagus - Muscularis                     515
Cells - Cultured fibroblasts               504
Breast - Mammary Tissue                    459
Artery - Aorta                             432
Heart - Left Ventricle                     432
Heart - Atrial Appendage                   429
Colon - Transverse                         406
Esophagus - Gastroesophageal Junction      375
Colon - Sigmoid                            373
Testis                                     361
Stomach                                    359
Pancreas                                   328
Pituitary                                  283
Adrenal Gland                              258
Brain - Cortex                             255
Brain - Caudate (basal ganglia)            246
Brain - Nucleus accumbens (basal ganglia)  246
Prostate                                   245
Brain - Cerebellum                         241
Spleen                                     241
Artery - Coronary                          240
Liver                                      226
Brain - Cerebellar Hemisphere              215
Brain - Frontal Cortex (BA9)               209
Brain - Putamen (basal ganglia)            205
Brain - Hypothalamus                       202
Brain - Hippocampus                        197
Small Intestine - Terminal Ileum           187
Ovary                                      180
Brain - Anterior cingulate cortex (BA24)   176
Cells - EBV-transformed lymphocytes        174
Minor Salivary Gland                       162
Brain - Spinal cord (cervical c-1)         159
Vagina                                     156
Brain - Amygdala                           152
Uterus                                     142
Brain - Substantia nigra                   139
Kidney - Cortex                             85
Bladder                                     21
Cervix - Endocervix                         10
Cervix - Ectocervix                          9
Fallopian Tube                               9
Kidney - Medulla                             4

We are only interested in those from the colorectal area.

colon.sample.df <- rnaseq.sample.df %>% dplyr::filter(SMTSD == "Colon - Sigmoid")
colon.sample.df

IV. Loading TPM data from GTEx

GTEx_Analysis_2017-06-05_v8_RNASeQCv1.1.9_gene_tpm.gct contains the gene TPMs.

Download this file by running:

wget https://storage.googleapis.com/adult-gtex/bulk-gex/v8/rna-seq/GTEx_Analysis_2017-06-05_v8_RNASeQCv1.1.9_gene_tpm.gct.gz -P data/GTEx/
tpm.df <- read.delim(paste0(DATA_DIR, "GTEx_Analysis_2017-06-05_v8_RNASeQCv1.1.9_gene_tpm.gct"),
  as.is = T, row.names = 1, check.names = FALSE, skip = 2
)
gene.names.df <- tpm.df[, "Description", drop = FALSE]
tpm.df <- tpm.df[, !(names(tpm.df) %in% c("Description"))]
{
  cat(paste("Number of genes in table: ", dim(tpm.df)[1]))
}
Number of genes in table:  56200

Perform some data preprocessing.

# Remove version number: https://www.rdocumentation.org/packages/grex/versions/1.9/topics/cleanid
tpm.df$ensembl <- cleanid(rownames(tpm.df))
head(tpm.df$ensembl)
[1] "ENSG00000223972" "ENSG00000227232" "ENSG00000278267" "ENSG00000243485" "ENSG00000237613" "ENSG00000268020"

FADD is one of the key genes involved in necroptosis.

# Create a named vector to map names to IDs
name_to_id <- setNames(rownames(gene.names.df), gene.names.df$Description)

# Create a named vector to map IDs to names
id_to_name <- setNames(gene.names.df$Description, rownames(gene.names.df))

# To retrieve the ID for 'FADD'
print(name_to_id[["FADD"]])
[1] "ENSG00000168040.4"
print(id_to_name[["ENSG00000168040.4"]])
[1] "FADD"

V. Loading RCD gene sets

Necroptosis

We obtain the gene set from the Human MSigDB Collections:

CAVEAT! GOBP_NECROPTOTIC_SIGNALING_PATHWAY contains only 8 genes.

necroptosis.genes <- msigdbr(species = "human", category = "C5", subcategory = "GO:BP") %>%
  dplyr::filter(gs_name == "GOBP_NECROPTOTIC_SIGNALING_PATHWAY")
necroptosis.genes

Ferroptosis

We obtain the gene set from the Human MSigDB Collections:

Note that there is another ferroptosis gene set: GOBP_FERROPTOSIS.
However, it contains only 10 genes (for comparison, WP_FERROPTOSIS contains 64 genes).

ferroptosis.genes <- msigdbr(species = "human", category = "C2", subcategory = "CP:WIKIPATHWAYS") %>%
  dplyr::filter(gs_name == "WP_FERROPTOSIS")
ferroptosis.genes

Pyroptosis

We obtain the gene set from the Human MSigDB Collections:

REACTOME_PYROPTOSIS contains 27 genes.

pyroptosis.genes <- msigdbr(species = "human", category = "C2", subcategory = "CP:REACTOME") %>%
  dplyr::filter(gs_name == "REACTOME_PYROPTOSIS")
pyroptosis.genes

VI. Exploratory Data Analysis

Select only the tissue samples (columns) from the colorectal area.

tpm.colon.df <- tpm.df %>% dplyr::select(c(ensembl, rownames(colon.sample.df)))
tpm.colon.df

Necroptosis

Get the TPM for the genes in the necroptosis gene set.

tpm.colon.necro.df <- tpm.colon.df %>% dplyr::filter(ensembl %in% necroptosis.genes$ensembl_gene)
tpm.colon.necro.df2 <- left_join(tpm.colon.necro.df, necroptosis.genes %>% dplyr::select(ensembl_gene, gene_symbol), by = c("ensembl" = "ensembl_gene"))
tpm.colon.necro.df$gene_symbol <- tpm.colon.necro.df2$gene_symbol
tpm.colon.necro.df

Compute the median TPM per gene.

gene.expressions.necro <- data.frame(
  row.names = tpm.colon.necro.df$gene_symbol,
  tissue = "Colon",
  tpm = matrixStats::rowMedians(as.matrix(tpm.colon.necro.df %>% dplyr::select(-c("ensembl", "gene_symbol"))))
)
gene.expressions.necro

Plot the gene expression.

ggplot(gene.expressions.necro, aes(y = tissue, x = rownames(gene.expressions.necro), fill = tpm)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "red") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(size = 9, hjust = 1)
  ) +
  labs(
    title = "Expression of necroptosis-related genes in GTEx colon tissues",
    x = "Gene",
    y = "Area",
    fill = "TPM"
  ) +
  geom_text(aes(label = tpm), vjust = 1)

Sanity Check: RIPK1 and necroptosis - https://www.nature.com/articles/s12276-022-00847-4

Ferroptosis

Get the TPM for the genes in the ferroptosis gene set.

tpm.colon.ferro.df <- tpm.colon.df %>% dplyr::filter(ensembl %in% ferroptosis.genes$ensembl_gene)
tpm.colon.ferro.df2 <- left_join(tpm.colon.ferro.df, ferroptosis.genes %>% dplyr::select(ensembl_gene, gene_symbol), by = c("ensembl" = "ensembl_gene"))
tpm.colon.ferro.df$gene_symbol <- tpm.colon.ferro.df2$gene_symbol
tpm.colon.ferro.df

Compute the median TPM per gene.

gene.expressions.ferro <- data.frame(
  row.names = tpm.colon.ferro.df$gene_symbol,
  tissue = "Colon",
  tpm = matrixStats::rowMedians(as.matrix(tpm.colon.ferro.df %>% dplyr::select(-c("ensembl", "gene_symbol"))))
)
gene.expressions.ferro

Plot the gene expression.

ggplot(gene.expressions.ferro, aes(y = tissue, x = rownames(gene.expressions.ferro), fill = tpm)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "red") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(size = 7, angle = 90, hjust = 1)
  ) +
  labs(
    title = "Expression of ferroptosis-related genes in GTEx colon tissues",
    x = "Gene",
    y = "Area",
    fill = "TPM"
  )

Sanity Check: FTH1 and ferroptosis - https://www.nature.com/articles/s41420-022-00902-z

Pyroptosis

Get the TPM for the genes in the pyroptosis gene set.

tpm.colon.pyro.df <- tpm.colon.df %>% dplyr::filter(ensembl %in% pyroptosis.genes$ensembl_gene)
tpm.colon.pyro.df2 <- left_join(tpm.colon.pyro.df, pyroptosis.genes %>% dplyr::select(ensembl_gene, gene_symbol), by = c("ensembl" = "ensembl_gene"))
tpm.colon.pyro.df$gene_symbol <- tpm.colon.pyro.df2$gene_symbol
tpm.colon.pyro.df

Compute the median TPM per gene.

gene.expressions.pyro <- data.frame(
  row.names = tpm.colon.pyro.df$gene_symbol,
  tissue = "Colon",
  tpm = matrixStats::rowMedians(as.matrix(tpm.colon.pyro.df %>% dplyr::select(-c("ensembl", "gene_symbol"))))
)
gene.expressions.pyro

Plot the gene expression.

ggplot(gene.expressions.pyro, aes(y = tissue, x = rownames(gene.expressions.pyro), fill = tpm)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "red") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(size = 7, angle = 90, hjust = 1)
  ) +
  labs(
    title = "Expression of pyroptosis-related genes in GTEx colon tissues",
    x = "Gene",
    y = "Area",
    fill = "TPM"
  )

Sanity Check: CHMP4B and pyroptosis - https://pubmed.ncbi.nlm.nih.gov/38823000/


  1. De La Salle University, Manila, Philippines, ↩︎

  2. De La Salle University, Manila, Philippines, ↩︎

  3. De La Salle University, Manila, Philippines, ↩︎

LS0tDQp0aXRsZTogIkV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMiDQphdXRob3I6IA0KICAtIEtpbSBXaWxsaWFtZSBMZWVeW0RlIExhIFNhbGxlIFVuaXZlcnNpdHksIE1hbmlsYSwgUGhpbGlwcGluZXMsIGtpbV9sZWVqcmFAZGxzdS5lZHUucGhdDQogIC0gTWFyayBFZHdhcmQgTS4gR29uemFsZXNeW0RlIExhIFNhbGxlIFVuaXZlcnNpdHksIE1hbmlsYSwgUGhpbGlwcGluZXMsIGdvbnphbGVzLm1hcmtlZHdhcmRAZ21haWwuY29tXQ0KICAtIERyLiBBbmlzaCBNLlMuIFNocmVzdGhhXltEZSBMYSBTYWxsZSBVbml2ZXJzaXR5LCBNYW5pbGEsIFBoaWxpcHBpbmVzLCBhbmlzaC5zaHJlc3RoYUBkbHN1LmVkdS5waF0NCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIEkuIFByZWxpbWluYXJpZXMNCg0KIyMjIExvYWRpbmcgbGlicmFyaWVzDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeSgidGlkeXZlcnNlIikNCmxpYnJhcnkoInRpYmJsZSIpDQpsaWJyYXJ5KCJtc2lnZGJyIikNCmxpYnJhcnkoImdncGxvdDIiKQ0KbGlicmFyeSgiVENHQWJpb2xpbmtzIikNCmxpYnJhcnkoIlJOQXNlcVFDIikNCmxpYnJhcnkoIkRFU2VxMiIpDQpsaWJyYXJ5KCJlbnNlbWJsZGIiKQ0KbGlicmFyeSgicHVycnIiKQ0KbGlicmFyeSgibWFncml0dHIiKQ0KbGlicmFyeSgidnNuIikNCmxpYnJhcnkoIm1hdHJpeFN0YXRzIikNCmxpYnJhcnkoImRwbHlyIikNCmxpYnJhcnkoImdyZXgiKQ0KYGBgDQoNCiMjIyBDb25zdGFudHMNCmBgYHtyfQ0KREFUQV9ESVIgPC0gImRhdGEvR1RFeC8iDQpgYGANCg0KIyMgSUkuIExvYWRpbmcgdGhlIEdURXggYW5ub3RhdGlvbnMNCg0KLSBgR1RFeF9BbmFseXNpc192OF9Bbm5vdGF0aW9uc19TYW1wbGVBdHRyaWJ1dGVzRFMudHh0YCAtIEEgZGUtaWRlbnRpZmllZCwgb3BlbiBhY2Nlc3MgdmVyc2lvbiBvZiB0aGUgc2FtcGxlIGFubm90YXRpb25zIGF2YWlsYWJsZSBpbiBkYkdhUCAoZGF0YWJhc2Ugb2YgZ2Vub3R5cGVzIGFuZCBwaGVub3R5cGVzKQ0KLSBgR1RFeF9BbmFseXNpc192OF9Bbm5vdGF0aW9uc19TdWJqZWN0UGhlbm90eXBlc0RTLnR4dGAgLSBBIGRlLWlkZW50aWZpZWQsIG9wZW4gYWNjZXNzIHZlcnNpb24gb2YgdGhlIHN1YmplY3QgcGhlbm90eXBlcyBhdmFpbGFibGUgaW4gZGJHYVAuCQ0KDQpEb3dubG9hZCB0aGVzZSBmaWxlcyBieSBydW5uaW5nOg0KYGBgDQp3Z2V0IGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9hZHVsdC1ndGV4L2Fubm90YXRpb25zL3Y4L21ldGFkYXRhLWZpbGVzL0dURXhfQW5hbHlzaXNfdjhfQW5ub3RhdGlvbnNfU2FtcGxlQXR0cmlidXRlc0RTLnR4dCAtUCBkYXRhL0dURXgvDQp3Z2V0IGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9hZHVsdC1ndGV4L2Fubm90YXRpb25zL3Y4L21ldGFkYXRhLWZpbGVzL0dURXhfQW5hbHlzaXNfdjhfQW5ub3RhdGlvbnNfU3ViamVjdFBoZW5vdHlwZXNEUy50eHQgLVAgZGF0YS9HVEV4Lw0KYGBgDQoNCmBgYHtyfQ0Kc2FtcGxlLmRmIDwtIHJlYWQuZGVsaW0ocGFzdGUwKERBVEFfRElSLCAiR1RFeF9BbmFseXNpc192OF9Bbm5vdGF0aW9uc19TYW1wbGVBdHRyaWJ1dGVzRFMudHh0IiksIGFzLmlzID0gVFJVRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gMSkNCnN1YmplY3QuZGYgPC0gcmVhZC5kZWxpbShwYXN0ZTAoREFUQV9ESVIsICJHVEV4X0FuYWx5c2lzX3Y4X0Fubm90YXRpb25zX1N1YmplY3RQaGVub3R5cGVzRFMudHh0IiksIGFzLmlzID0gVFJVRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gMSkNCmBgYA0KDQpUaGUgYERUSEhSRFlgIGNvbHVtbiByZWZlcnMgdG8gdGhlIDQtcG9pbnQgSGFyZHkgc2NhbGU6IGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHJvamVjdHMvZ2FwL2NnaS1iaW4vdmFyaWFibGUuY2dpP3N0dWR5X2lkPXBoczAwMDQyNC52NC5wMSZwaHY9MTY5MDkyDQoNClJlZmVyIHRvIHRoZSBtZXRhZGF0YSBmaWxlcyBoZXJlIGZvciBtb3JlIGluZm9ybWF0aW9uOiBodHRwczovL2d0ZXhwb3J0YWwub3JnL2hvbWUvZG93bmxvYWRzL2FkdWx0LWd0ZXgvbWV0YWRhdGENCg0KYGBge3J9DQpzdWJqZWN0LmRmDQpgYGANClJlZmVyIHRvIHRoZSBtZXRhZGF0YSBmaWxlcyBoZXJlIGZvciBtb3JlIGluZm9ybWF0aW9uOiBodHRwczovL2d0ZXhwb3J0YWwub3JnL2hvbWUvZG93bmxvYWRzL2FkdWx0LWd0ZXgvbWV0YWRhdGENCg0KYGBge3J9DQpzYW1wbGUuZGYNCmBgYA0KDQpFeHRyYWN0IGVudHJpZXMgdGhhdCBwZXJ0YWluIHRvIHRyYW5zY3JpcHRvbWljIChSTkEpIGRhdGEuDQoNCmBgYHtyfQ0Kcm5hc2VxLnNhbXBsZS5kZiA8LSBzYW1wbGUuZGZbc2FtcGxlLmRmWyJTTUFGUlpFIl0gPT0gIlJOQVNFUSIsIF0NCnJuYXNlcS5zYW1wbGUuZGYNCmBgYA0KDQojIyBJSUkuIEZpbHRlcmluZyBjb2xvbiBzYW1wbGVzDQoNClRoZSBgU01UU0RgIGNvbHVtbiByZWZlcnMgdG8gdGhlIHRpc3N1ZSB0eXBlIChpLmUuLCB0aGUgYXJlYSBmcm9tIHdoaWNoIHRoZSBzYW1wbGUgd2FzIHRha2VuKS4NCg0KYGBge3J9DQphcy5tYXRyaXgoc29ydCh0YWJsZShybmFzZXEuc2FtcGxlLmRmWyJTTVRTRCJdKSwgZGVjcmVhc2luZyA9IFRSVUUpKQ0KYGBgDQpXZSBhcmUgb25seSBpbnRlcmVzdGVkIGluIHRob3NlIGZyb20gdGhlIGNvbG9yZWN0YWwgYXJlYS4NCg0KYGBge3J9DQpjb2xvbi5zYW1wbGUuZGYgPC0gcm5hc2VxLnNhbXBsZS5kZiAlPiUgZHBseXI6OmZpbHRlcihTTVRTRCA9PSAiQ29sb24gLSBTaWdtb2lkIikNCmNvbG9uLnNhbXBsZS5kZg0KYGBgDQoNCiMjIElWLiBMb2FkaW5nIFRQTSBkYXRhIGZyb20gR1RFeA0KDQpgR1RFeF9BbmFseXNpc18yMDE3LTA2LTA1X3Y4X1JOQVNlUUN2MS4xLjlfZ2VuZV90cG0uZ2N0YCBjb250YWlucyB0aGUgZ2VuZSBUUE1zLg0KDQpEb3dubG9hZCB0aGlzIGZpbGUgYnkgcnVubmluZzoNCmBgYA0Kd2dldCBodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb20vYWR1bHQtZ3RleC9idWxrLWdleC92OC9ybmEtc2VxL0dURXhfQW5hbHlzaXNfMjAxNy0wNi0wNV92OF9STkFTZVFDdjEuMS45X2dlbmVfdHBtLmdjdC5neiAtUCBkYXRhL0dURXgvDQpgYGANCg0KYGBge3J9DQp0cG0uZGYgPC0gcmVhZC5kZWxpbShwYXN0ZTAoREFUQV9ESVIsICJHVEV4X0FuYWx5c2lzXzIwMTctMDYtMDVfdjhfUk5BU2VRQ3YxLjEuOV9nZW5lX3RwbS5nY3QiKSwNCiAgYXMuaXMgPSBULCByb3cubmFtZXMgPSAxLCBjaGVjay5uYW1lcyA9IEZBTFNFLCBza2lwID0gMg0KKQ0KZ2VuZS5uYW1lcy5kZiA8LSB0cG0uZGZbLCAiRGVzY3JpcHRpb24iLCBkcm9wID0gRkFMU0VdDQp0cG0uZGYgPC0gdHBtLmRmWywgIShuYW1lcyh0cG0uZGYpICVpbiUgYygiRGVzY3JpcHRpb24iKSldDQp7DQogIGNhdChwYXN0ZSgiTnVtYmVyIG9mIGdlbmVzIGluIHRhYmxlOiAiLCBkaW0odHBtLmRmKVsxXSkpDQp9DQpgYGANClBlcmZvcm0gc29tZSBkYXRhIHByZXByb2Nlc3NpbmcuDQoNCmBgYHtyfQ0KIyBSZW1vdmUgdmVyc2lvbiBudW1iZXI6IGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9ncmV4L3ZlcnNpb25zLzEuOS90b3BpY3MvY2xlYW5pZA0KdHBtLmRmJGVuc2VtYmwgPC0gY2xlYW5pZChyb3duYW1lcyh0cG0uZGYpKQ0KaGVhZCh0cG0uZGYkZW5zZW1ibCkNCmBgYA0KRkFERCBpcyBvbmUgb2YgdGhlIGtleSBnZW5lcyBpbnZvbHZlZCBpbiBuZWNyb3B0b3Npcy4NCg0KYGBge3J9DQojIENyZWF0ZSBhIG5hbWVkIHZlY3RvciB0byBtYXAgbmFtZXMgdG8gSURzDQpuYW1lX3RvX2lkIDwtIHNldE5hbWVzKHJvd25hbWVzKGdlbmUubmFtZXMuZGYpLCBnZW5lLm5hbWVzLmRmJERlc2NyaXB0aW9uKQ0KDQojIENyZWF0ZSBhIG5hbWVkIHZlY3RvciB0byBtYXAgSURzIHRvIG5hbWVzDQppZF90b19uYW1lIDwtIHNldE5hbWVzKGdlbmUubmFtZXMuZGYkRGVzY3JpcHRpb24sIHJvd25hbWVzKGdlbmUubmFtZXMuZGYpKQ0KDQojIFRvIHJldHJpZXZlIHRoZSBJRCBmb3IgJ0ZBREQnDQpwcmludChuYW1lX3RvX2lkW1siRkFERCJdXSkNCnByaW50KGlkX3RvX25hbWVbWyJFTlNHMDAwMDAxNjgwNDAuNCJdXSkNCmBgYA0KDQojIyBWLiBMb2FkaW5nIFJDRCBnZW5lIHNldHMNCg0KIyMjIE5lY3JvcHRvc2lzDQoNCldlIG9idGFpbiB0aGUgZ2VuZSBzZXQgZnJvbSB0aGUgSHVtYW4gTVNpZ0RCIENvbGxlY3Rpb25zOiAgDQoNCi0gYEdPQlBfTkVDUk9QVE9USUNfU0lHTkFMSU5HX1BBVEhXQVlgIHJlZmVycyB0byB0aGUgbmVjcm9wdG9zaXMgZ2VuZSBzZXQgKGZvdW5kIHZpYSBNU2lnREIncyBzZWFyY2ggZnVuY3Rpb25hbGl0eTogaHR0cHM6Ly93d3cuZ3NlYS1tc2lnZGIub3JnL2dzZWEvbXNpZ2RiL2h1bWFuL3NlYXJjaC5qc3ApLiAgDQotIFRoZSBjYXRlZ29yeSBhbmQgc3ViY2F0ZWdvcnkgcGFyYW1ldGVycyB3ZXJlIGRlY2lkZWQgYmFzZWQgb24gdGhpcyBnZW5lIHNldC4gIA0KLSBgQzVgIGNvbnNpc3RzIG9mIGdlbmVzIGFubm90YXRlZCBieSB0aGUgc2FtZSBvbnRvbG9neSB0ZXJtIChodHRwczovL3d3dy5nc2VhLW1zaWdkYi5vcmcvZ3NlYS9tc2lnZGIvKS4gIA0KLSBgR086QlBgIHJlZmVycyB0byB0aGUgImJpb2xvZ2ljYWwgcHJvY2VzcyIgY2F0ZWdvcnkgaW4gR2VuZSBPbnRvbG9neS4NCg0KQ0FWRUFUISBgR09CUF9ORUNST1BUT1RJQ19TSUdOQUxJTkdfUEFUSFdBWWAgY29udGFpbnMgb25seSA4IGdlbmVzLg0KDQpgYGB7cn0NCm5lY3JvcHRvc2lzLmdlbmVzIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJodW1hbiIsIGNhdGVnb3J5ID0gIkM1Iiwgc3ViY2F0ZWdvcnkgPSAiR086QlAiKSAlPiUNCiAgZHBseXI6OmZpbHRlcihnc19uYW1lID09ICJHT0JQX05FQ1JPUFRPVElDX1NJR05BTElOR19QQVRIV0FZIikNCm5lY3JvcHRvc2lzLmdlbmVzDQpgYGANCg0KIyMjIEZlcnJvcHRvc2lzDQogDQpXZSBvYnRhaW4gdGhlIGdlbmUgc2V0IGZyb20gdGhlIEh1bWFuIE1TaWdEQiBDb2xsZWN0aW9uczoNCg0KLSBgV1BfRkVSUk9QVE9TSVNgIHJlZmVycyB0byB0aGUgZmVycm9wdG9zaXMgZ2VuZSBzZXQgKGZvdW5kIHZpYSBNU2lnREIncyBzZWFyY2ggZnVuY3Rpb25hbGl0eTogaHR0cHM6Ly93d3cuZ3NlYS1tc2lnZGIub3JnL2dzZWEvbXNpZ2RiL2h1bWFuL3NlYXJjaC5qc3ApLg0KLSBUaGUgY2F0ZWdvcnkgYW5kIHN1YmNhdGVnb3J5IHBhcmFtZXRlcnMgd2VyZSBkZWNpZGVkIGJhc2VkIG9uIHRoaXMgZ2VuZSBzZXQuICAgDQotIGBDMmAgY29uc2lzdHMgb2YgdGhlIGN1cmF0ZWQgZ2VuZSBzZXRzIChodHRwczovL3d3dy5nc2VhLW1zaWdkYi5vcmcvZ3NlYS9tc2lnZGIvKS4gIA0KLSBgQ1A6V0lLSVBBVEhXQVlTYCByZWZlcnMgdG8gdGhlIGN1cmF0ZWQgZ2VuZSBzZXQgZnJvbSBXaWtpUGF0aHdheXMuDQoNCk5vdGUgdGhhdCB0aGVyZSBpcyBhbm90aGVyIGZlcnJvcHRvc2lzIGdlbmUgc2V0OiBgR09CUF9GRVJST1BUT1NJU2AuIDxicj4NCkhvd2V2ZXIsIGl0IGNvbnRhaW5zIG9ubHkgMTAgZ2VuZXMgKGZvciBjb21wYXJpc29uLCBgV1BfRkVSUk9QVE9TSVNgIGNvbnRhaW5zIDY0IGdlbmVzKS4NCg0KYGBge3J9DQpmZXJyb3B0b3Npcy5nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiaHVtYW4iLCBjYXRlZ29yeSA9ICJDMiIsIHN1YmNhdGVnb3J5ID0gIkNQOldJS0lQQVRIV0FZUyIpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKGdzX25hbWUgPT0gIldQX0ZFUlJPUFRPU0lTIikNCmZlcnJvcHRvc2lzLmdlbmVzDQpgYGANCg0KIyMjIFB5cm9wdG9zaXMNCg0KV2Ugb2J0YWluIHRoZSBnZW5lIHNldCBmcm9tIHRoZSBIdW1hbiBNU2lnREIgQ29sbGVjdGlvbnM6DQoNCi0gYFJFQUNUT01FX1BZUk9QVE9TSVNgIHJlZmVycyB0byB0aGUgcHlyb3B0b3NpcyBnZW5lIHNldCAoZm91bmQgdmlhIE1TaWdEQidzIHNlYXJjaCBmdW5jdGlvbmFsaXR5OiBodHRwczovL3d3dy5nc2VhLW1zaWdkYi5vcmcvZ3NlYS9tc2lnZGIvaHVtYW4vc2VhcmNoLmpzcCkuDQotIFRoZSBjYXRlZ29yeSBhbmQgc3ViY2F0ZWdvcnkgcGFyYW1ldGVycyB3ZXJlIGRlY2lkZWQgYmFzZWQgb24gdGhpcyBnZW5lIHNldC4NCi0gYEMyYCBjb25zaXN0cyBvZiB0aGUgY3VyYXRlZCBnZW5lIHNldHMgKGh0dHBzOi8vd3d3LmdzZWEtbXNpZ2RiLm9yZy9nc2VhL21zaWdkYi8pLg0KLSBgQ1A6UkVBQ1RPTUVgIHJlZmVycyB0byB0aGUgY3VyYXRlZCBnZW5lIHNldCBmcm9tIFJlYWN0b21lLg0KDQpgUkVBQ1RPTUVfUFlST1BUT1NJU2AgY29udGFpbnMgMjcgZ2VuZXMuDQoNCmBgYHtyfQ0KcHlyb3B0b3Npcy5nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiaHVtYW4iLCBjYXRlZ29yeSA9ICJDMiIsIHN1YmNhdGVnb3J5ID0gIkNQOlJFQUNUT01FIikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoZ3NfbmFtZSA9PSAiUkVBQ1RPTUVfUFlST1BUT1NJUyIpDQpweXJvcHRvc2lzLmdlbmVzDQpgYGANCg0KIyMgVkkuIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMNCg0KU2VsZWN0IG9ubHkgdGhlIHRpc3N1ZSBzYW1wbGVzIChjb2x1bW5zKSBmcm9tIHRoZSBjb2xvcmVjdGFsIGFyZWEuDQoNCmBgYHtyfQ0KdHBtLmNvbG9uLmRmIDwtIHRwbS5kZiAlPiUgZHBseXI6OnNlbGVjdChjKGVuc2VtYmwsIHJvd25hbWVzKGNvbG9uLnNhbXBsZS5kZikpKQ0KdHBtLmNvbG9uLmRmDQpgYGANCg0KIyMjIE5lY3JvcHRvc2lzDQoNCkdldCB0aGUgVFBNIGZvciB0aGUgZ2VuZXMgaW4gdGhlIG5lY3JvcHRvc2lzIGdlbmUgc2V0Lg0KDQpgYGB7cn0NCnRwbS5jb2xvbi5uZWNyby5kZiA8LSB0cG0uY29sb24uZGYgJT4lIGRwbHlyOjpmaWx0ZXIoZW5zZW1ibCAlaW4lIG5lY3JvcHRvc2lzLmdlbmVzJGVuc2VtYmxfZ2VuZSkNCnRwbS5jb2xvbi5uZWNyby5kZjIgPC0gbGVmdF9qb2luKHRwbS5jb2xvbi5uZWNyby5kZiwgbmVjcm9wdG9zaXMuZ2VuZXMgJT4lIGRwbHlyOjpzZWxlY3QoZW5zZW1ibF9nZW5lLCBnZW5lX3N5bWJvbCksIGJ5ID0gYygiZW5zZW1ibCIgPSAiZW5zZW1ibF9nZW5lIikpDQp0cG0uY29sb24ubmVjcm8uZGYkZ2VuZV9zeW1ib2wgPC0gdHBtLmNvbG9uLm5lY3JvLmRmMiRnZW5lX3N5bWJvbA0KdHBtLmNvbG9uLm5lY3JvLmRmDQpgYGANCg0KQ29tcHV0ZSB0aGUgbWVkaWFuIFRQTSBwZXIgZ2VuZS4NCg0KYGBge3J9DQpnZW5lLmV4cHJlc3Npb25zLm5lY3JvIDwtIGRhdGEuZnJhbWUoDQogIHJvdy5uYW1lcyA9IHRwbS5jb2xvbi5uZWNyby5kZiRnZW5lX3N5bWJvbCwNCiAgdGlzc3VlID0gIkNvbG9uIiwNCiAgdHBtID0gbWF0cml4U3RhdHM6OnJvd01lZGlhbnMoYXMubWF0cml4KHRwbS5jb2xvbi5uZWNyby5kZiAlPiUgZHBseXI6OnNlbGVjdCgtYygiZW5zZW1ibCIsICJnZW5lX3N5bWJvbCIpKSkpDQopDQpnZW5lLmV4cHJlc3Npb25zLm5lY3JvDQpgYGANCg0KUGxvdCB0aGUgZ2VuZSBleHByZXNzaW9uLg0KDQpgYGB7cn0NCmdncGxvdChnZW5lLmV4cHJlc3Npb25zLm5lY3JvLCBhZXMoeSA9IHRpc3N1ZSwgeCA9IHJvd25hbWVzKGdlbmUuZXhwcmVzc2lvbnMubmVjcm8pLCBmaWxsID0gdHBtKSkgKw0KICBnZW9tX3RpbGUoKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJyZWQiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBoanVzdCA9IDEpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkV4cHJlc3Npb24gb2YgbmVjcm9wdG9zaXMtcmVsYXRlZCBnZW5lcyBpbiBHVEV4IGNvbG9uIHRpc3N1ZXMiLA0KICAgIHggPSAiR2VuZSIsDQogICAgeSA9ICJBcmVhIiwNCiAgICBmaWxsID0gIlRQTSINCiAgKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSB0cG0pLCB2anVzdCA9IDEpDQpgYGANCioqU2FuaXR5IENoZWNrOioqIFJJUEsxIGFuZCBuZWNyb3B0b3NpcyAtIGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczEyMjc2LTAyMi0wMDg0Ny00DQoNCiMjIyBGZXJyb3B0b3Npcw0KDQpHZXQgdGhlIFRQTSBmb3IgdGhlIGdlbmVzIGluIHRoZSBmZXJyb3B0b3NpcyBnZW5lIHNldC4NCg0KYGBge3J9DQp0cG0uY29sb24uZmVycm8uZGYgPC0gdHBtLmNvbG9uLmRmICU+JSBkcGx5cjo6ZmlsdGVyKGVuc2VtYmwgJWluJSBmZXJyb3B0b3Npcy5nZW5lcyRlbnNlbWJsX2dlbmUpDQp0cG0uY29sb24uZmVycm8uZGYyIDwtIGxlZnRfam9pbih0cG0uY29sb24uZmVycm8uZGYsIGZlcnJvcHRvc2lzLmdlbmVzICU+JSBkcGx5cjo6c2VsZWN0KGVuc2VtYmxfZ2VuZSwgZ2VuZV9zeW1ib2wpLCBieSA9IGMoImVuc2VtYmwiID0gImVuc2VtYmxfZ2VuZSIpKQ0KdHBtLmNvbG9uLmZlcnJvLmRmJGdlbmVfc3ltYm9sIDwtIHRwbS5jb2xvbi5mZXJyby5kZjIkZ2VuZV9zeW1ib2wNCnRwbS5jb2xvbi5mZXJyby5kZg0KYGBgDQpDb21wdXRlIHRoZSBtZWRpYW4gVFBNIHBlciBnZW5lLg0KDQpgYGB7cn0NCmdlbmUuZXhwcmVzc2lvbnMuZmVycm8gPC0gZGF0YS5mcmFtZSgNCiAgcm93Lm5hbWVzID0gdHBtLmNvbG9uLmZlcnJvLmRmJGdlbmVfc3ltYm9sLA0KICB0aXNzdWUgPSAiQ29sb24iLA0KICB0cG0gPSBtYXRyaXhTdGF0czo6cm93TWVkaWFucyhhcy5tYXRyaXgodHBtLmNvbG9uLmZlcnJvLmRmICU+JSBkcGx5cjo6c2VsZWN0KC1jKCJlbnNlbWJsIiwgImdlbmVfc3ltYm9sIikpKSkNCikNCmdlbmUuZXhwcmVzc2lvbnMuZmVycm8NCmBgYA0KUGxvdCB0aGUgZ2VuZSBleHByZXNzaW9uLg0KDQpgYGB7cn0NCmdncGxvdChnZW5lLmV4cHJlc3Npb25zLmZlcnJvLCBhZXMoeSA9IHRpc3N1ZSwgeCA9IHJvd25hbWVzKGdlbmUuZXhwcmVzc2lvbnMuZmVycm8pLCBmaWxsID0gdHBtKSkgKw0KICBnZW9tX3RpbGUoKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJyZWQiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3LCBhbmdsZSA9IDkwLCBoanVzdCA9IDEpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkV4cHJlc3Npb24gb2YgZmVycm9wdG9zaXMtcmVsYXRlZCBnZW5lcyBpbiBHVEV4IGNvbG9uIHRpc3N1ZXMiLA0KICAgIHggPSAiR2VuZSIsDQogICAgeSA9ICJBcmVhIiwNCiAgICBmaWxsID0gIlRQTSINCiAgKQ0KYGBgDQoqKlNhbml0eSBDaGVjazoqKiBGVEgxIGFuZCBmZXJyb3B0b3NpcyAtIGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczQxNDIwLTAyMi0wMDkwMi16DQoNCiMjIyBQeXJvcHRvc2lzDQoNCkdldCB0aGUgVFBNIGZvciB0aGUgZ2VuZXMgaW4gdGhlIHB5cm9wdG9zaXMgZ2VuZSBzZXQuDQoNCmBgYHtyfQ0KdHBtLmNvbG9uLnB5cm8uZGYgPC0gdHBtLmNvbG9uLmRmICU+JSBkcGx5cjo6ZmlsdGVyKGVuc2VtYmwgJWluJSBweXJvcHRvc2lzLmdlbmVzJGVuc2VtYmxfZ2VuZSkNCnRwbS5jb2xvbi5weXJvLmRmMiA8LSBsZWZ0X2pvaW4odHBtLmNvbG9uLnB5cm8uZGYsIHB5cm9wdG9zaXMuZ2VuZXMgJT4lIGRwbHlyOjpzZWxlY3QoZW5zZW1ibF9nZW5lLCBnZW5lX3N5bWJvbCksIGJ5ID0gYygiZW5zZW1ibCIgPSAiZW5zZW1ibF9nZW5lIikpDQp0cG0uY29sb24ucHlyby5kZiRnZW5lX3N5bWJvbCA8LSB0cG0uY29sb24ucHlyby5kZjIkZ2VuZV9zeW1ib2wNCnRwbS5jb2xvbi5weXJvLmRmDQpgYGANCg0KQ29tcHV0ZSB0aGUgbWVkaWFuIFRQTSBwZXIgZ2VuZS4NCg0KYGBge3J9DQpnZW5lLmV4cHJlc3Npb25zLnB5cm8gPC0gZGF0YS5mcmFtZSgNCiAgcm93Lm5hbWVzID0gdHBtLmNvbG9uLnB5cm8uZGYkZ2VuZV9zeW1ib2wsDQogIHRpc3N1ZSA9ICJDb2xvbiIsDQogIHRwbSA9IG1hdHJpeFN0YXRzOjpyb3dNZWRpYW5zKGFzLm1hdHJpeCh0cG0uY29sb24ucHlyby5kZiAlPiUgZHBseXI6OnNlbGVjdCgtYygiZW5zZW1ibCIsICJnZW5lX3N5bWJvbCIpKSkpDQopDQpnZW5lLmV4cHJlc3Npb25zLnB5cm8NCmBgYA0KDQpQbG90IHRoZSBnZW5lIGV4cHJlc3Npb24uDQoNCmBgYHtyfQ0KZ2dwbG90KGdlbmUuZXhwcmVzc2lvbnMucHlybywgYWVzKHkgPSB0aXNzdWUsIHggPSByb3duYW1lcyhnZW5lLmV4cHJlc3Npb25zLnB5cm8pLCBmaWxsID0gdHBtKSkgKw0KICBnZW9tX3RpbGUoKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJyZWQiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3LCBhbmdsZSA9IDkwLCBoanVzdCA9IDEpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkV4cHJlc3Npb24gb2YgcHlyb3B0b3Npcy1yZWxhdGVkIGdlbmVzIGluIEdURXggY29sb24gdGlzc3VlcyIsDQogICAgeCA9ICJHZW5lIiwNCiAgICB5ID0gIkFyZWEiLA0KICAgIGZpbGwgPSAiVFBNIg0KICApDQpgYGANCioqU2FuaXR5IENoZWNrOioqIENITVA0QiBhbmQgcHlyb3B0b3NpcyAtIGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzg4MjMwMDAv